
                1    **********************************************************
                2    *                                                        *
                3    *                    N a d a b o o t                     *
                4    *                                                        *
                5    *            Michael J. Mahon - June 23, 2004            *
                6    *                 Revised Oct 20, 2004                   *
                7    *                                                        *
                8    *             Copyright (c) 1996, 2003, 2004             *
                9    *                                                        *
                10   *   Nadaboot is ROM boot code for a diskless Unenhanced  *
                11   *   Apple //e which replaces the self-test code.  It     *
                12   *   causes the //e to boot from the "master" (ID=1)      *
                13   *   machine on the network.                              *
                14   *                                                        *
                15   *                                                        *
                16   **********************************************************
                17   *                                                        *
                18   *                    Change History                      *
                19   *                                                        *
                20   *   10/20/04:                                            *
                21   *                                                        *
                22   *   Added "warm start" capability based on $3F2 vector.  *
                23   *                                                        *
                24   *   Moved "bootself" to $3CC (out of way of ProDOS).     *
                25   *                                                        *
                26   *   Reorganized to use NADANET "put" files.              *
                27   *                                                        *
                28   *   06/29/04:                                            *
                29   *                                                        *
                30   *   Changed random ID generation to rely upon paddle 3   *
                31   *   timeout, since paddle 3 is already being used as a   *
                32   *   pulse stretcher for the "send" LED.  This requires   *
                33   *   that each board have a sufficiently different valued *
                34   *   resistor for paddle 3 to make the counted values     *
                35   *   unique.  It also allows static ID assignment.        *
                36   *                                                        *
                37   *   06/23/04:                                            *
                38   *                                                        *
                39   *   Re-randomized ID after GETID failure to make boot    *
                40   *   code more robust in case of random collisions.       *
                41   *                                                        *
                42   *   Removed SENDLONG from boot code.                     *
                43   *                                                        *
                44   *   Made "packet"/"message" nomenclature consistent.     *
                45   *                                                        *
                46   *   05/26/04:                                            *
                47   *                                                        *
                48   *   Added MONITOR function to boot ROM for debugging.    *
                49   *                                                        *
                50   *   05/24/04:                                            *
                51   *                                                        *
                52   *   Added conditional assembly flags and alternate code  *
                53   *   to trigger the paddle timer when entering SENDMSG    *
                54   *   (to allow for a simple hardware "send" indicator).   *
                55   *                                                        *
                56   *   05/13/04:                                            *
                57   *                                                        *
                58   *   Initial version.                                     *
                59   *                                                        *
                60   **********************************************************
 
                     ===== Page 2 -  October 20, 2004 =====
  
                62   ******************** Version setup ***********************
                63   
                64            org   $C400      ; (Replaces self-test)
                65   master   equ   0          ; Non-master version
                66   crate    equ   0          ; Non-Crate version
                67   mserve   equ   0          ; Non-Message Server version
                68   ROMboot  equ   1          ; ROM boot version
 
                     ===== Page 3 -  October 20, 2004 =====
  
                70           put   NADACONST  
               >1    * Constant definitions
               >2    
               >3    px       equ   $FF        ; Constant to force page x-ing
               >4    cyperms  equ   1020       ; Cycles per ms. (really 1020.4)
               >5    
               >6    * Protocol constants
               >7    
               >8    arbtime  equ   1          ; Min arbitration time (ms)
               >9    ]cy      equ   arbtime*cyperms ; Arbtime in cycles
               >10   ]cpx     equ   11         ; Cycles per X iteration
               >11   ]cpy     equ   ]cpx*256+4 ; Cycles per Y iteration
               >12   arby     equ   ]cy/]cpy+1 ; Number of Y iterations
               >13   ]ym1     equ   arby-1     ; Number of "full" Y iterations
               >14   ]prod    equ   ]ym1*]cpy  ; Cycles of "full" iterations
               >15   ]rem     equ   ]cy-]prod  ; Remainder in cycles
               >16   arbx     equ   ]rem/]cpx  ; Remainder in X iterations
               >17   
               >18            err   arby-1     ; Server "wait idle" is single
               >19                             ; loop, so 'arby' must be 1.
               >20   
               >21   idletime equ   20         ; Idle polling timeout (ms.)
               >22                             ; (stay under 51ms for Zip Chip)
               >23   ]cy      equ   idletime*cyperms ; Timeout in cycles
               >24   ]cpx     equ   11         ; Cycles per X iteration
               >25   ]cpy     equ   ]cpx*256+4 ; Cycles per Y iteration
               >26   idleto   equ   ]cy/]cpy+1 ; Number of Y iterations
               >27   
               >28   reqto    equ   arby       ; Timeout within protocol is
               >29                             ;  minimum arbitration time.
               >30   
               >31   maxgap   equ   101        ; Max intra-pkt gap (cycles)
               >32   gapwait  equ   maxgap/]cpx+1 ; Iterations to detect gap
               >33   
               >34   reqtime  equ   3000       ; Req response timeout (ms.)
               >35   rqperiod equ   20         ; Milliseconds between retrys
               >36   reqdelay equ   rqperiod-3 ; ARB+SEND+RCV timeout = 3ms.
               >37   maxretry equ   reqtime/rqperiod ; # of retries
               >38   
               >39   maxreqrt equ   3          ; Max # of request retries
               >40   
               >41   bootdly  equ   1000       ; Time (ms) to delay after
               >42                             ;  GETID before broadcasting
               >43                             ;   BOOT request and code.
               >44   bootcnt  equ   bootdly/idletime ; SERVER timeout count
 
                     ===== Page 4 -  October 20, 2004 =====
  
               >46   * Apple ][ definitions
               >47   
               >48   an       equ   $C058      ; Annunciator 0 base addr
               >49   an0      equ   an         
               >50   an1      equ   an+2       
               >51   an2      equ   an+4       
               >52   an3      equ   an+6       
               >53   
               >54   pb       equ   $C061      ; "Pushbutton" 0 base addr
               >55   pb0      equ   pb         
               >56   pb1      equ   pb+1       
               >57   pb2      equ   pb+2       
               >58   
               >59   keybd    equ   $C000      ; Keyboard port
               >60   VBL      equ   $C019      ; Vertical blanking
               >61   spkr     equ   $C030      ; Speaker toggle
               >62   ptrig    equ   $C070      ; Paddle trigger
               >63   
               >64   dsk6off  equ   $C0E8      ; Deselect 5.25" disk in slot 6
               >65   
               >66   SOFTEV   equ   $3F2       ; Soft re-entry vector
               >67   PWREDUP  equ   $3F4       ; Powered-Up check byte
               >68   
               >69   * Mapping of hardware resources
               >70   
               >71   dsend    equ   an1        ; Data 'send'
               >72   drecv    equ   pb1        ; Data 'receive'
               >73   zipslow  equ   dsk6off    ; Zip Chip 'slow mode' for 51 ms.
               >74   
               >75   * Page zero variables
               >76   
               >77   leng     equ   $EB        ; Length: 1..256 (0 ==> 256)
               >78   ckbyte   equ   $EC        ; Check byte
               >79   ptr      equ   $ED        ; Data buffer pointer (0..leng-1)
               >80   address  equ   $FC        ; Scratch addr of local data
               >81   length   equ   $FE        ; Scratch length of local data
 
                     ===== Page 5 -  October 20, 2004 =====
  
                71           use   NADAMACS   
               >1    ***************** Macro definitions ********************
               >2    
               >3    inc16    mac              
               >4             inc   ]1         ; Increment 16-bit word.
               >5             do    ]1+1/$100  ; If ]1 is non-page zero
               >6             bne   *+5        ; - No carry.
               >7             else             ; Else if ]1 on page zero
               >8             bne   *+4        ; - No carry.
               >9             fin              
               >10            inc   ]1+1       ; Propagate carry.
               >11            eom              
               >12   
               >13   mov16    mac              
               >14            lda   ]1         ; Move 2 bytes
               >15            sta   ]2         
               >16            if    #=]1
               >17            lda   ]1/$100    ; high byte of immediate
               >18            else             
               >19            lda   1+]1       
               >20            fin              
               >21            sta   1+]2       
               >22            eom              
               >23   
               >24   delay    mac              
               >25            ldx   #]1/5      ; (5 cycles per iteration)
               >26   ]delay   dex              
               >27            bne   ]delay     
               >28            eom              
               >29   
               >30   dlyms    mac              
               >31            ldy   #]1        ; Delay 1ms. per iteration
               >32   ]dly     delay 1020-4     ; Cycles per ms. - 4
               >33            dey              
               >34            bne   ]dly       
               >35            eom              
               >36   
               >37   align    mac              
               >38            ds    *-1/]1*]1+]1-* 
               >39            eom              
               >40   
 
                     ===== Page 6 -  October 20, 2004 =====
  
                72           put   NADADEFS   
               >1    **********************************************************
               >2    *                                                        *
               >3    *                 NadaNet Definitions                    *
               >4    *                                                        *
               >5    *            Michael J. Mahon - Oct 13, 2004             *
               >6    *                 Revised Oct 20, 2004                   *
               >7    *                                                        *
               >8    *                  Copyright (c) 2004                    *
               >9    *                                                        *
               >10   **********************************************************
               >11   
               >12   ********************* Entry points ***********************
               >13   
C400: 00       >39   ROMcksum db    0*0        ; Checksum compensation byte
               >40   
C401: 4C 1C C4 >41   entry    jmp   RESET      ; Gets control on Reset
C404: 4C 17 C6 >42   sendpkt  jmp   SENDPKT    ; Vector to ROM SENDPKT
C407: 4C 01 C7 >43   rcvpkt   jmp   RCVPKT     ; Vector to ROM RCVPKT
C40A: 4C 05 C7 >44   rcvptr   jmp   RCVPTR     ; Vector to ROM RCVPTR
C40D: 4C 5A C5 >45   monitor  jmp   MONITOR    ; Vector to ROM MONITOR
               >47   
               >48   ********** Control Packet Definition **********
               >49   
               >50            dum   0          ; Control packet format:
0000: 00       >51   req      ds    1          ;   Request
0001: 00       >52   mod      ds    1          ;   Request modifier
0002: 00       >53   dst      ds    1          ;   Destination ID (0 = bcast)
0003: 00       >54   frm      ds    1          ;   Sending ID (never 0)
0004: 00 00    >55   adr      ds    2          ;   Address field
0006: 00 00    >56   len      ds    2          ;   Length field
               >57                             ; =========================
               >58   lenctl   ds    0          ; Length of control packet
               >59            dend             
               >60   
               >61   * Request codes and modifiers
               >62   
               >63            dum   1          ; Request codes (0 invalid):
0001: 00       >64   r_PEEK   ds    1          ;   PEEK request
0002: 00       >65   r_POKE   ds    1          ;   POKE request
0003: 00       >66   r_CALL   ds    1          ;   CALL request
0004: 00       >67   r_PUTMSG ds    1          ;   PUTMSG request
0005: 00       >68   r_GETMSG ds    1          ;   GETMSG request
0006: 00       >69   r_GETID  ds    1          ;   GETID request
0007: 00       >70   r_BOOT   ds    1          ;   BOOT request
0008: 00       >71   r_BPOKE  ds    1          ;   Broadcast POKE request
0009: 00       >72   r_PEKINC ds    1          ;   PEEK & INCrement request
               >73                             ; ==========================
               >74   maxreq   ds    0          ;   Max request + 1
               >75            dend             
               >76   
               >77            dum   1          ; Modifier codes (0 invalid):
0001: 00       >78   rm_REQ   ds    1          ;   Request
0002: 00       >79   rm_ACK   ds    1          ;   Acknowledge
0003: 00       >80   rm_DACK  ds    1          ;   Data Acknowledge
0004: 00       >81   rm_NAK   ds    1          ;   Negative Acknowledge
               >82            dend             
 
                     ===== Page 7 -  October 20, 2004 =====
  
               >84   *********** Non-page zero variables ************
               >85   
               >86            dum   $3CC       ; Fixed memory vector
03CC: 00       >87   bootself db    0          ; Machine ID from BOOT
03CD: 4C 00 00 >88   warmstrt jmp   0*0        ; Warm start SERVE loop entry
               >89   nadapage equ   *-1        ; NADANET load page
               >90            dend             
               >91   
               >93            dum   $280       ; Template for ROM boot data
               >95   
0280: 00       >96   self     db    0          ; Our own machine ID (1..15)
0281: 00 00 00 >97   sbuf     ds    lenctl     ; Control pkt send buffer
0289: 00 00 00 >98   rbuf     ds    lenctl     ; Control pkt receive buffer
0291: 5C       >99   arbxv    db    arbx       ; Arbitrate X iters (modified)
0292: 01       >100  arbyv    db    arby       ; Arbitrate Y iters (modified)
0293: 01       >101  tolim    db    reqto      ; RCVPKT timeout limit
0294: 00       >102  sendck   db    0          ; 1 = send cksum flag
0295: 00 00    >103  locaddr  dw    0          ; Local address of req data
               >104  
               >105  * Counters
               >106  
0297: 00       >107  reqretry db    0          ; Request retries remaining
0298: 96       >108  retrylim db    maxretry   ; Limit of REQUEST retries
0299: 00       >109  retrycnt db    0          ; REQUEST retry count
029A: 00 00    >110  errprot  dw    0          ; Protocol error count
029C: 00 00    >111  ckerr    dw    0          ; Checksum error count
029E: 01       >112  reqctr   db    %00000001  ; Shifting counts mod 8
029F: 00       >113  servecnt db    0          ; SERVE iterations (0=256)
               >126  
               >128           dend             
 
                     ===== Page 8 -  October 20, 2004 =====
  
                73           put   BOOTCODE   
               >1    **************** Boot code definitions *******************
               >2    
               >3    * Apple ][ ROM subroutines
               >4    
               >5    PRBL2    equ   $F94A      ; Display (X) blanks
               >6    PREAD    equ   $FB1E      ; Read PDL(X) into Y
               >7    HOME     equ   $FC58      ; Clear display
               >8    PRBYTE   equ   $FDDA      ; Display A as hex byte
               >9    COUT     equ   $FDED      ; Display character in A
               >10   BELL     equ   $FF3A      ; Beep for 100ms.
               >11   
               >12   * Boot data and definitions
               >13   
C410: C1 F0 F0 >14   idmsg    asc   "AppleCrate $" ; Sign-on message
               >15   idlen    equ   *-idmsg    ; Length of message
               >16   
               >17   bootwait equ   5000       ; BOOT wait timeout (ms)
               >18   bootct   equ   bootwait/idletime ; BOOT RCV retries
               >19   
               >20   
               >21   *--------------------------------------------------------*
               >22   *         Requester                  Master (ID=1)       *
               >23   *  ========================     =======================  *
               >24   *  GETID  REQ              ====>                         *
               >25   *                          <==== GETID  ACK (ID)         *
               >26   *  GETID  DACK             ====>                         *
               >27   *--------(approx. 'bootdly' milliseconds later)----------*
               >28   *                          <==== BOOT  REQ (addr,leng)   *
               >29   *                          <==== Data                    *
               >30   *                            :                           *
               >31   *                          <==== Data                    *
               >32   *--------------------------------------------------------*
 
                     ===== Page 9 -  October 20, 2004 =====
  
               >34   **********************************************************
               >35   *                                                        *
               >36   *                       R E S E T                        *
               >37   *                                                        *
               >38   *            Michael J. Mahon - Oct 20, 2004             *
               >39   *                                                        *
               >40   *                  Copyright (c) 2004                    *
               >41   *                                                        *
               >42   *  Upon hardware reset, this routine looks at the $3F2   *
               >43   *  vector and decides whether to warm restart or reboot. *
               >44   *                                                        *
               >45   **********************************************************
               >46   
C41C: AD F3 03 >47   RESET    lda   SOFTEV+1   ; Is the PWREDUP byte
C41F: 49 A5    >48            eor   #$A5       ;  correct for a warm
C421: CD F4 03 >49            cmp   PWREDUP    ;   restart?
C424: D0 03    >50            bne   :boot      ; -No, boot required.
C426: 6C F2 03 >51            jmp   (SOFTEV)   ; -Yes, give code control.
               >52   
C429: A9 03    >53   :boot    lda   #3         ; Initialize for 3
C42B: 8D 98 02 >54            sta   retrylim   ;  'request' retrys
               >55   * (Fall into BOOT)
 
                     ===== Page 10 -  October 20, 2004 =====
  
               >57   **********************************************************
               >58   *                                                        *
               >59   *                        B O O T                         *
               >60   *                                                        *
               >61   *            Michael J. Mahon - May 13, 2004             *
               >62   *                 Revised Oct 20, 2004                   *
               >63   *                                                        *
               >64   *                  Copyright (c) 2004                    *
               >65   *                                                        *
               >66   *  Boot a diskless machine from the network.             *
               >67   *                                                        *
               >68   *  This version of BOOT is active, and, becuase it is    *
               >69   *  longer than $200, is intended for use in a modified   *
               >70   *  Unenhanced //e ROM, replacing the self-test code from *
               >71   *  $C400..C7FF.                                          *
               >72   *                                                        *
               >73   *  BOOT does the following steps:                        *
               >74   *     1. Reads Paddle 3 and uses it to form a unique     *
               >75   *        "pseudo-ID" to avoid arbitration collisions.    *
               >76   *     2. Sends a GET ID request to the master (ID=1) to  *
               >77   *        announce presence, request boot.  Then receives *
               >78   *        ACK with real machine ID assigned.  Responds to *
               >79   *        master with DACK using newly assigned ID.       *
               >80   *     3. Goes into a RCVCTL loop waiting for the BOOT    *
               >81   *        request (broadcast) which contains the address  *
               >82   *        and length of the following boot code stream.   *
               >83   *     4. Receives the boot code into memory.             *
               >84   *     5. If any error, retry starting at step 2.         *
               >85   *     6. Set up warm start address and PWREDUP byte.     *
               >86   *     7. Clear screen and display ID message.            *
               >87   *     8. Jump to start address.                          *
               >88   *                                                        *
               >89   **********************************************************
               >90   
C42E: A9 01    >91   BOOT     lda   #1         ; Set up ID of master
C430: 8D 83 02 >92            sta   sbuf+dst   
C433: A2 03    >93            ldx   #3         ; Set to read Paddle 3
C435: 20 1E FB >94            jsr   PREAD      ; Read Paddle 3 (to Y)
C438: 98       >95            tya              ; Create pseudo-ID
C439: 09 80    >96            ora   #$80       ; (pseudo is >127)
C43B: 20 D8 C4 >97            jsr   setid      
C43E: 20 3A FF >98   :retry   jsr   BELL       ; Delay 100ms & blink LED
C441: A9 01    >99            lda   #reqto     ; Set RCVPKT timeout
C443: 8D 93 02 >100           sta   tolim      ;  to min arb time.
C446: A9 06    >101           lda   #r_GETID   ; Perform a GETID
C448: 20 EC C4 >102           jsr   REQUEST    ;  request.
C44B: B0 F1    >103           bcs   :retry     ; GETID failed.
C44D: AD 8D 02 >104           lda   rbuf+adr   ; Set new assigned ID.
C450: 20 D8 C4 >105           jsr   setid      
C453: A9 03    >106           lda   #rm_DACK   ; Send DACK with
C455: 20 02 C6 >107           jsr   SENDRSP    ;  newly assigned ID.
C458: A9 FA    >108           lda   #bootct    ; Set retry interval
C45A: 8D 97 02 >109           sta   reqretry   
C45D: A9 08    >110           lda   #idleto    ; Set RCVPKT timeout
C45F: 8D 93 02 >111           sta   tolim      ;  to 20ms.
C462: 20 FB C6 >112  :again   jsr   RCVCTL     ; Get a control pkt
C465: 90 09    >113           bcc   :ok        ; -good pkt.
C467: D0 F9    >114           bne   :again     ; -bad cksum.
C469: CE 97 02 >115           dec   reqretry   ; -timed out. Repeat for
C46C: D0 F4    >116           bne   :again     ;   bootct * timeout secs.
C46E: F0 CE    >117           beq   :retry     ; Then repeat request.
               >118  
C470: AD 8B 02 >119  :ok      lda   rbuf+dst   
C473: F0 05    >120           beq   :bcast     ; Broadcast or
C475: CD 80 02 >121           cmp   self       ;  sent to us?
C478: D0 E8    >122           bne   :again     ; -No, try again.
C47A: AD 89 02 >123  :bcast   lda   rbuf+req   
C47D: C9 07    >124           cmp   #r_BOOT    ; and BOOT
C47F: D0 E1    >125           bne   :again     
C481: AD 8A 02 >126           lda   rbuf+mod   
 
                     ===== Page 11 -  October 20, 2004 =====
 
C484: C9 01    >127           cmp   #rm_REQ    ; and "request"
C486: D0 DA    >128           bne   :again     
C488: A9 01    >129           lda   #reqto     ; Set RCVPKT timeout
C48A: 8D 93 02 >130           sta   tolim      ;  short again.
               >131           mov16 rbuf+adr;address ; Start address
C48D: AD 8D 02 >131           lda   rbuf+adr   ; Move 2 bytes
C490: 85 FC    >131           sta   address    
C492: AD 8E 02 >131           lda   1+rbuf+adr 
C495: 85 FD    >131           sta   1+address  
               >131           eom              
               >132           mov16 rbuf+len;length  ; Length
C497: AD 8F 02 >132           lda   rbuf+len   ; Move 2 bytes
C49A: 85 FE    >132           sta   length     
C49C: AD 90 02 >132           lda   1+rbuf+len 
C49F: 85 FF    >132           sta   1+length   
               >132           eom              
C4A1: 20 A3 C7 >133           jsr   RCVLONG    ; Read the boot code.
C4A4: B0 98    >134           bcs   :retry     ; -error, retry request.
C4A6: AD 8D 02 >135           lda   rbuf+adr   ; Set up SOFTEV vector
C4A9: 8D F2 03 >136           sta   SOFTEV     
C4AC: AD 8E 02 >137           lda   rbuf+adr+1 
C4AF: 8D F3 03 >138           sta   SOFTEV+1   
C4B2: 49 A5    >139           eor   #$A5       ; Compute power-up byte
C4B4: 8D F4 03 >140           sta   PWREDUP    ;  and save it for RESET.
C4B7: 20 58 FC >141           jsr   HOME       ; Clear the display
C4BA: A2 0D    >142           ldx   #40-idlen/2-1 ; and print enough
C4BC: 20 4A F9 >143           jsr   PRBL2      ;     blanks to center
C4BF: A0 00    >144           ldy   #0         
C4C1: B9 10 C4 >145  :msgloop lda   idmsg,y    ;      the banner.
C4C4: 20 ED FD >146           jsr   COUT       
C4C7: C8       >147           iny              
C4C8: C0 0C    >148           cpy   #idlen     
C4CA: 90 F5    >149           bcc   :msgloop   
C4CC: AD 80 02 >150           lda   self       ; Pass ID to running code
C4CF: 8D CC 03 >151           sta   bootself   ;  in fixed address.
C4D2: 20 DA FD >152           jsr   PRBYTE     ; Display ID
C4D5: 6C F2 03 >153           jmp   (SOFTEV)   ; Give code control...
 
                     ===== Page 12 -  October 20, 2004 =====
  
                74           put   INITSERVE  ; (just for 'setid')
               >46   **********************************************************
               >47   *                                                        *
               >48   *                       S E T I D                        *
               >49   *                                                        *
               >50   *            Michael J. Mahon - May 13, 2004             *
               >51   *                  Revised Oct 05, 2004                  *
               >52   *                                                        *
               >53   *                   Copyright (c) 2004                   *
               >54   *                                                        *
               >55   *  Set machine ID to contents of A register and reset    *
               >56   *  the arbitration delay to 'arbtime' plus 22 cycles     *
               >57   *  times the machine ID, to avoid collisions.            *
               >58   *                                                        *
               >59   *  Delay from last arbitration poll to bus lock is 10    *
               >60   *  cycles, so 22 (2 * 11 cycles) increment provides a    *
               >61   *  little insurance.                                     *
               >62   *                                                        *
               >63   **********************************************************
               >64   
C4D8: 8D 80 02 >65   setid    sta   self       ; Machine ID (1..15)
C4DB: 8D 84 02 >66            sta   sbuf+frm   ; Set sender field.
C4DE: 0A       >67            asl              ;  *2
C4DF: 69 5C    >68            adc   #arbx      ; Add to base
C4E1: 8D 91 02 >69            sta   arbxv      ;  delay.
C4E4: A9 01    >70            lda   #arby      
C4E6: 69 00    >71            adc   #0         ; Propagate carry.
C4E8: 8D 92 02 >72            sta   arbyv      
C4EB: 60       >73            rts              
 
                     ===== Page 13 -  October 20, 2004 =====
  
                75           put   PEEKPOKECALL ; (for 'request')
               >267  **********************************************************
               >268  *                                                        *
               >269  *                     R E Q U E S T                      *
               >270  *                                                        *
               >271  *            Michael J. Mahon - April 20, 2004           *
               >272  *                  Revised Oct 12, 2004                  *
               >273  *                                                        *
               >274  *                Copyright (c) 1996, 2004                *
               >275  *                                                        *
               >276  *  Handle request protocol for the request in A & 'sbuf'.*
               >277  *                                                        *
               >278  *  Retry the protocol for up to 'reqtime' ms. (up to     *
               >279  *  'retrylim' times).  If successful, return with valid  *
               >280  *  response in 'rbuf' and Carry clear.                   *
               >281  *                                                        *
               >282  *  If request timed out, return with Carry set and A=0.  *
               >283  *                                                        *
               >284  *  If NAK received, return with Carry set and A>0.       *
               >285  *                                                        *
               >286  *  REQUEST performs the following steps:                 *
               >287  *     1. Complete control pkt in 'sbuf' (request in A)   *
               >288  *     2. Arbitrate for the use of the bus                *
               >289  *     3. Send the request specified in 'sbuf'            *
               >290  *     4. Receive the control response into 'rbuf'        *
               >291  *     5. Check 'rbuf' for a valid, expected response     *
               >292  *     6. Retry steps 2 to 5 up to 'retrylim' times       *
               >293  *     7. When ACKed, NAKed, or timed-out, return         *
               >294  *                                                        *
               >295  **********************************************************
               >296  
C4EC: 8D 81 02 >297  REQUEST  sta   sbuf+req   ; Store request code.
C4EF: A9 01    >298           lda   #rm_REQ    ; Put REQ in the
C4F1: 8D 82 02 >299           sta   sbuf+mod   ;  mod field, and
C4F4: AD 98 02 >300           lda   retrylim   ;  init retry counter
C4F7: 8D 99 02 >301           sta   retrycnt   
C4FA: AD 99 02 >302  :retry   lda   retrycnt   ; Timed out?
C4FD: F0 59    >303           beq   :err       ; - Yes, return w/ C set, A=0
C4FF: CE 99 02 >304           dec   retrycnt   ; Dec retry counter.
C502: 20 AB C5 >305           jsr   ARBTRATE   ; Get the bus.
C505: 20 11 C6 >306           jsr   SENDCTL    ; Send request in 'sbuf'.
C508: 20 FB C6 >307           jsr   RCVCTL     ; Receive response in 'rbuf'.
C50B: 90 19    >308           bcc   :ok        ; - clean packet received.
C50D: 08       >309           php              ; Save flags,
               >310           dlyms reqdelay   ;  delay a few ms.
C50E: A0 11    >310           ldy   #reqdelay  ; Delay 1ms. per iteration
               >310  ]dly     delay 1020-4     ; Cycles per ms. - 4
C510: A2 CB    >310           ldx   #1020-4/5  ; (5 cycles per iteration)
C512: CA       >310  ]delay   dex              
C513: D0 FD    >310           bne   ]delay     
               >310           eom              
C515: 88       >310           dey              
C516: D0 F8    >310           bne   ]dly       
               >310           eom              
C518: 28       >311           plp              ;   and restore flags.
C519: F0 DF    >312           beq   :retry     ; - no packet received.
               >313           inc16 ckerr      ; - count checksum errors.
C51B: EE 9C 02 >313           inc   ckerr      ; Increment 16-bit word.
C51E: D0 03    >313           bne   *+5        ; - No carry.
C520: EE 9D 02 >313           inc   ckerr+1    ; Propagate carry.
               >313           eom              
C523: 4C FA C4 >314           jmp   :retry     ;    and try again...
               >315  
C526: AD 8B 02 >316  :ok      lda   rbuf+dst   ; Message received, is
C529: CD 80 02 >317           cmp   self       ;  it for us?
C52C: D0 1B    >318           bne   :proterr   ; - No, error.
C52E: AD 83 02 >319           lda   sbuf+dst   ; - Yes.  Is it from
C531: CD 8C 02 >320           cmp   rbuf+frm   ;    our destination?
C534: D0 13    >321           bne   :proterr   ; - No.  Protocol error.
C536: AD 89 02 >322           lda   rbuf+req   ; - Yes.  Is it what
 
                     ===== Page 14 -  October 20, 2004 =====
 
C539: CD 81 02 >323           cmp   sbuf+req   ;    we expected?
C53C: D0 0B    >324           bne   :proterr   ; - No, error.
C53E: AD 8A 02 >325           lda   rbuf+mod   ; - Yes, so far...
C541: C9 02    >326           cmp   #rm_ACK    ; Is it an ACK?
C543: F0 0F    >327           beq   :good      ; - Yes, valid response!
C545: C9 04    >328           cmp   #rm_NAK    ; Is it a NAK?
C547: F0 0D    >329           beq   :nakexit   ; -Yes, return w/ C set, A=1
               >330  :proterr inc16 errprot    ; - No, count protocol errors.
C549: EE 9A 02 >330           inc   errprot    ; Increment 16-bit word.
C54C: D0 03    >330           bne   *+5        ; - No carry.
C54E: EE 9B 02 >330           inc   errprot+1  ; Propagate carry.
               >330           eom              
C551: 4C FA C4 >331           jmp   :retry     ;    and try again...
               >332  
C554: 18       >333  :good    clc              ; Signal good ACK
C555: 60       >334           rts              ;  and return.
               >335  
C556: A9 01    >336  :nakexit lda   #1         ; Signal NAK
C558: 38       >337  :err     sec              ; Signal error
C559: 60       >338           rts              ;  and return.
 
                     ===== Page 15 -  October 20, 2004 =====
  
                76           put   SENDRCV    
               >1    **********************************************************
               >2    *                                                        *
               >3    *                LOW-LEVEL PACKET FORMAT                 *
               >4    *                                                        *
               >5    * Start of packet:                                       *
               >6    *                                                        *
               >7    *  --//---+---------+      +---------+-----+-----+-//->  *
               >8    *  Locked |   ONE   | ZERO |   ONE   |Bit7 |Bit6 |       *
               >9    *  or Idle|   36cy  | 10cy |   17cy  | 9cy | 9cy |       *
               >10   *  --//---+         +------+         +-----+-----+-//->  *
               >11   *         |                          |                   *
               >12   *         |<-------- Start --------->|<-- 8 data --//->  *
               >13   *                    Signal                bits          *
               >14   *                    (63cy)               (75cy)         *
               >15   *                                                        *
               >16   *  (Note: Bit4 data is lengthened by 3 cyc, to 12 cyc.)  *
               >17   *                                                        *
               >18   * Interbyte separator:                                   *
               >19   *                                                        *
               >20   *  >-//-----+-----+-------+           +-----+------//->  *
               >21   *           |Bit0 |  ONE  |    ZERO   |Bit7 |            *
               >22   *           | 9cy |  12cy |    19cy   | 9cy |            *
               >23   *  >-//-----+-----+       +-----------+-----+------//->  *
               >24   *                 |       |           |                  *
               >25   *  >-//- 8 data ->|     Servo         |<- 8 data --//->  *
               >26   *         bits    |   transition      |    bits          *
               >27   *                 |                   |                  *
               >28   *                 |<--- Interbyte --->|                  *
               >29   *                       separator                        *
               >30   *                         (31cy)                         *
               >31   *                                                        *
               >32   * Checkbyte separator:                                   *
               >33   *                                                        *
               >34   * >-// --+-----+-------+                 +-----+---//->  *
               >35   *        |Bit0 |  ONE  |      ZERO       |Bit7 |         *
               >36   *        | 9cy |  12cy |      26cy       | 9cy |         *
               >37   * >-//---+-----+       +-----------------+-----+---//->  *
               >38   *              |       |                 |               *
               >39   * >-//- data ->|     Servo               |<- data -//->  *
               >40   *       bits   |   transition            |   bits        *
               >41   *   (last data)|                         |(checkbyte)    *
               >42   *              |<------ Extended ------->|               *
               >43   *                      check byte                        *
               >44   *                       separator                        *
               >45   *                        (38cy)                          *
               >46   *                                                        *
               >47   * Packet end:                                            *
               >48   *                                                        *
               >49   *  >-//--+-----+-----+-------+                           *
               >50   *        |Bit1 |Bit0 |  ONE  |         (Idle)            *
               >51   *        | 9cy | 9cy |  12cy |                           *
               >52   *  >-//--+-----+-----+       +---------------------//->  *
               >53   *                    |                                   *
               >54   *  >-//--- End of -->|                                   *
               >55   *        checkbyte                                       *
               >56   *                                                        *
               >57   **********************************************************
 
                     ===== Page 16 -  October 20, 2004 =====
  
               >60   **********************************************************
               >61   *                                                        *
               >62   *                    M O N I T O R                       *
               >63   *                                                        *
               >64   *            Michael J. Mahon - May 26, 2004             *
               >65   *                 Revised Oct 12, 2004                   *
               >66   *                                                        *
               >67   *                  Copyright (c) 2004                    *
               >68   *                                                        *
               >69   *  Receive the first 8 bytes of each packet into buffer  *
               >70   *  in memory, together with its checksum residue.        *
               >71   *                                                        *
               >72   *  RCVPKT timeouts are recorded as 2-byte $DEAD marks    *
               >73   *  and are temporarily increased to 20ms.                *
               >74   *                                                        *
               >75   **********************************************************
               >76   
               >77   * Definitions
               >78   
               >79   bufstrt  equ   $2000      ; Start of monitor buffer
               >81   bufend   equ   $C000-$100 ; Ending page of monitor buffer
               >85   monlen   equ   lenctl     ; Monitor record data length
               >86   toflg1   equ   $DE        ; Timeout flag byte 1
               >87   toflg2   equ   $AD        ; Timeout flag byte 2
               >88   
               >89   MONITOR  mov16 #bufstrt;ptr ; Set start of buffer
C55A: A9 00    >89            lda   #bufstrt   ; Move 2 bytes
C55C: 85 ED    >89            sta   ptr        
C55E: A9 20    >89            lda   #bufstrt/$100 ; high byte of immediate
C560: 85 EE    >89            sta   1+ptr      
               >89            eom              
C562: A2 08    >90            ldx   #idleto    ; Set RCVPKT timeout
C564: 8E 93 02 >91            stx   tolim      ;  to 20 ms.
C567: A2 0A    >92   :waitgap ldx   #gapwait   ; Wait for interpacket gap.
C569: CD E8 C0 >93            cmp   zipslow    ; Slow Zip Chip to 1MHz.
C56C: AD 62 C0 >94   :wait    lda   drecv      ; Net idle?
C56F: 30 F6    >95            bmi   :waitgap   ; -No, start over.
C571: CA       >96            dex              ; -Yes, count down
C572: D0 F8    >97            bne   :wait      ;   until satisfied.
C574: A2 08    >98   :next    ldx   #monlen    ; Set length
C576: 20 05 C7 >99            jsr   RCVPTR     ;  to receive...
C579: A0 08    >100           ldy   #monlen    ; Point to cksum residue
C57B: AA       >101           tax              ; Save cksum residue
C57C: 90 0B    >102           bcc   :store     ; -Good packet.
C57E: D0 09    >103           bne   :store     ; -Cksum error.
C580: A9 DE    >104           lda   #toflg1    ; -Timeout.  Flag
C582: A0 00    >105           ldy   #0         ;   it in buffer.
C584: 91 ED    >106           sta   (ptr),y    
C586: A9 AD    >107           lda   #toflg2    
C588: C8       >108           iny              
C589: 91 ED    >109  :store   sta   (ptr),y    ; Store byte in buffer
C58B: 98       >110           tya              ; Inc ptr by record
C58C: 38       >111           sec              ;  length + 1.
C58D: 65 ED    >112           adc   ptr        
C58F: 85 ED    >113           sta   ptr        
C591: A9 00    >114           lda   #0         
C593: 65 EE    >115           adc   ptr+1      
C595: 85 EE    >116           sta   ptr+1      
C597: C9 BF    >117           cmp   #>bufend   ; Buffer full?
C599: B0 0A    >118           bcs   :end       ; -Yes, stop.
C59B: AD 00 C0 >119           lda   keybd      ; Key pressed?
C59E: 30 05    >120           bmi   :end       ; -Yes, stop.
C5A0: 8A       >121           txa              ; Recover cksum residue
C5A1: F0 D1    >122           beq   :next      ; -Good, receive next.
C5A3: D0 C2    >123           bne   :waitgap   ; -Bad, wait next gap.
               >124  
C5A5: A2 01    >125  :end     ldx   #reqto     ; Restore timeout to
C5A7: 8E 93 02 >126           stx   tolim      ;  minimum arb time.
C5AA: 60       >127           rts              
 
                     ===== Page 17 -  October 20, 2004 =====
  
               >130  **********************************************************
               >131  *                                                        *
               >132  *                    A R B T R A T E                     *
               >133  *                                                        *
               >134  *             Michael J. Mahon - May 1, 1996             *
               >135  *                 Revised Oct 13, 2004                   *
               >136  *                                                        *
               >137  *                   Copyright (c) 1996                   *
               >138  *                                                        *
               >139  *  Waits until bus has been idle for 'arbtime' plus      *
               >140  *  machine id # * 22 cycles, then locks bus and returns. *
               >141  *                                                        *
               >142  **********************************************************
               >143  
C5AB: AC 92 02 >144  ARBTRATE ldy   arbyv      ; Set up Y iterations
C5AE: AE 91 02 >145           ldx   arbxv      ;  and initial X iterations
C5B1: CD E8 C0 >146           cmp   zipslow    ; Zip Chip to 1MHz mode.
C5B4: 2C 62 C0 >147  :waitidl bit   drecv      ; Wait for idle bus.
C5B7: 30 F2    >148           bmi   ARBTRATE   ; - not this time!
C5B9: CA       >149           dex              
C5BA: D0 F8    >150           bne   :waitidl   ; ...not yet.
C5BC: 88       >151           dey              
C5BD: D0 F5    >152           bne   :waitidl   ; ...not yet.
C5BF: 8D 5B C0 >153           sta   dsend+1    ; Got it!  Lock the bus
C5C2: 60       >154           rts              ;  and return.
 
                     ===== Page 18 -  October 20, 2004 =====
  
               >156           align 256        ; Align to next page.
C5C3: 00 00 00 >156           ds    *-1/256*256+256-* 
               >156           eom              
               >157                            ; (Timing-critical code)
               >158  
               >159  **********************************************************
               >160  *                                                        *
               >161  *                     S E N D P K T                      *
               >162  *                                                        *
               >163  *           Michael J. Mahon - April 15, 1996            *
               >164  *                 Revised Oct 12, 2004                   *
               >165  *                                                        *
               >166  *             Copyright (c) 1996, 2003, 2004             *
               >167  *                                                        *
               >168  *  Sends (X) bytes (1..256) starting at (A,Y) to the     *
               >169  *  currently selected machine(s).                        *
               >170  *                                                        *
               >171  *  SENDPKT does the following steps:                     *
               >172  *     1. Put Zip Chip in 'slow mode' for >38,000 cycles  *
               >173  *     2. Send start signal: 36 cyc ONE, 10 ZERO, 17 ONE. *
               >174  *     3. Send (X) bytes (at 106 cycles/byte)             *
               >175  *     4. Send one check byte (+7 extra byte sep. cycles) *
               >176  *     5. Returns with Carry clear.                       *
               >177  *                                                        *
               >178  *  SENDCTL performs a SENDPKT on the control packet      *
               >179  *  send buffer 'sbuf'.                                   *
               >180  *                                                        *
               >181  *  SENDRSP builds a packet specified by A in 'sbuf'      *
               >182  *  for the request in 'rbuf', then sends it.             *
               >183  *                                                        *
               >184  *  SENDACK builds an ACK packet in 'sbuf' for the        *
               >185  *  request in 'rbuf', then sends it.                     *
               >186  *                                                        *
               >187  *  To obtain maximum sending speed (9 cycles/bit), the   *
               >188  *  actual sending code is unrolled into two parts, one   *
               >189  *  that sends the four high bits, and one that sends the *
               >190  *  four low bits.  This division is necessary to permit  *
               >191  *  relative branches to "cover" the code.  This split    *
               >192  *  requires an extra branch between sending bit 4 and    *
               >193  *  sending bit 3, which lengthens bit 4 from 9 to 12     *
               >194  *  cycles.                                               *
               >195  *                                                        *
               >196  **********************************************************
               >197  
C600: A9 02    >198  SENDACK  lda   #rm_ACK    ; Build an ACK packet
C602: 8D 82 02 >199  SENDRSP  sta   sbuf+mod   ; Store modifier in 'sbuf'
C605: AD 89 02 >200           lda   rbuf+req   ; Same code as request
C608: 8D 81 02 >201           sta   sbuf+req   ;  code.
C60B: AD 8C 02 >202           lda   rbuf+frm   
C60E: 8D 83 02 >203           sta   sbuf+dst   ; Destination (= requester)
C611: A9 81    >204  SENDCTL  lda   #<sbuf     ; Control pkt send buffer
C613: A0 02    >205           ldy   #>sbuf     
C615: A2 08    >206           ldx   #lenctl    
C617: CD 70 C0 >210  SENDPKT  cmp   ptrig      ; Trigger paddle timer
C61A: 8D 5B C0 >212           sta   dsend+1    ; Send start signal ONE
C61D: 85 ED    >213           sta   ptr        ; A = start address lo
C61F: 84 EE    >214           sty   ptr+1      ; Y = start address hi
C621: 86 EB    >215           stx   leng       ; X = length: 1..256 (0=256)
C623: 86 EC    >216           stx   ckbyte     ; Seed ckbyte with length.
C625: A2 00    >217           ldx   #0         ; X = 0 for abs,X addressing
C627: A0 00    >218           ldy   #0         ; Y = ptr to next data byte
C629: A9 01    >219           lda   #1         ; Set flag to
C62B: 8D 94 02 >220           sta   sendck     ;  send ckbyte at end.
C62E: 18       >221           clc              ; Ensure C clear at exit
C62F: 08       >222           php              ; Save interrupt state
C630: 78       >223           sei              ;  and disable interrupts.
C631: 8D 5A C0 >224           sta   dsend+0    ; Begin a 10-cycle ZERO.
C634: EA       >225           nop              
C635: EA       >226           nop              
C636: EA       >227           nop              
 
                     ===== Page 19 -  October 20, 2004 =====
 
C637: 8D 5B C0 >228           sta   dsend+1    ; Start a 17-cycle ONE
C63A: 4C 9F C6 >229           jmp   :sendata   
               >230  
C63D: 8D 5A C0 >231  :bit00   sta   dsend+0    ; Send ZERO (4 cyc)
C640: 90 4D    >232           bcc   :nxbyte    ; This byte is finished.
               >233  
C642: 8D 5A C0 >234  :bit10   sta   dsend+0    ; Send ZERO (4 cyc)
C645: 2A       >235           rol              ; Bit 0 to Carry
C646: 90 F5    >236           bcc   :bit00     ; Handle zero
C648: 9D 5B C0 >237           sta   dsend+1,x  ; Send ONE (5 cyc)
C64B: B0 42    >238           bcs   :nxbyte    ; This byte is finished.
               >239  
C64D: 8D 5A C0 >240  :bit20   sta   dsend+0    ; Send ZERO (4 cyc)
C650: 2A       >241           rol              ; Bit 1 to Carry
C651: 90 EF    >242           bcc   :bit10     ; Handle zero
C653: 9D 5B C0 >243           sta   dsend+1,x  ; Send ONE (5 cyc)
C656: 2A       >244           rol              ; Bit 0 to Carry
C657: 90 E4    >245           bcc   :bit00     ; Handle zero
C659: 9D 5B C0 >246           sta   dsend+1,x  ; Send ONE (5 cyc)
C65C: B0 31    >247           bcs   :nxbyte    ; This byte is finished.
               >248  
C65E: 8D 5A C0 >249  :bit30   sta   dsend+0    ; Send ZERO (4 cyc)
C661: 2A       >250           rol              ; Bit 2 to Carry
C662: 90 E9    >251           bcc   :bit20     ; Handle zero
C664: 9D 5B C0 >252           sta   dsend+1,x  ; Send ONE (5 cyc)
C667: 2A       >253           rol              ; Bit 1 to Carry
C668: 90 D8    >254           bcc   :bit10     ; Handle zero
C66A: 9D 5B C0 >255           sta   dsend+1,x  ; Send ONE (5 cyc)
C66D: 2A       >256           rol              ; Bit 0 to Carry
C66E: 90 CD    >257           bcc   :bit00     ; Handle zero
C670: 9D 5B C0 >258           sta   dsend+1,x  ; Send ONE (5 cyc)
C673: B0 1A    >259           bcs   :nxbyte    ; This byte is finished.
               >260  
C675: 2A       >261  :sendlo  rol              ; Bit 3 to Carry
C676: 90 E6    >262           bcc   :bit30     ; Handle zero
C678: 9D 5B C0 >263           sta   dsend+1,x  ; Send ONE (5 cyc)
C67B: 2A       >264           rol              ; Bit 2 to Carry
C67C: 90 CF    >265           bcc   :bit20     ; Handle zero
C67E: 9D 5B C0 >266           sta   dsend+1,x  ; Send ONE (5 cyc)
C681: 2A       >267           rol              ; Bit 1 to Carry
C682: 90 BE    >268           bcc   :bit10     ; Handle zero
C684: 9D 5B C0 >269           sta   dsend+1,x  ; Send ONE (5 cyc)
C687: 2A       >270           rol              ; Bit 0 to Carry
C688: 90 B3    >271           bcc   :bit00     ; Handle zero
C68A: 9D 5B C0 >272           sta   dsend+1,x  ; Send ONE (5 cyc)
C68D: B0 00    >273           bcs   :nxbyte    ; This byte is finished.
               >274  
C68F: 2A       >275  :nxbyte  rol              ; Restore A = data for cksum
C690: 8D 5B C0 >276           sta   dsend+1    ; Start 12-cycle ONE.
C693: 45 EC    >277           eor   ckbyte     ; Compute checksum
C695: 85 EC    >278           sta   ckbyte     ;  and save it.
C697: C8       >279           iny              ; Increment data pointer
C698: 8D 5A C0 >280           sta   dsend+0    ; Send ZERO (servo transition)
C69B: C4 EB    >281           cpy   leng       ; Done?
C69D: F0 54    >282           beq   :done      ;  -yes, check end.
C69F: B1 ED    >283  :sendata lda   (ptr),y    ; Get next byte (5/6 cyc)
C6A1: 2A       >284  :senda   rol              ; Bit 7 to Carry
C6A2: 90 17    >285           bcc   :bit70     ; Handle zero
C6A4: 9D 5B C0 >286           sta   dsend+1,x  ; Send ONE (5 cyc)
C6A7: 2A       >287           rol              ; Bit 6 to Carry
C6A8: 90 28    >288           bcc   :bit60     ; Handle zero
C6AA: 9D 5B C0 >289           sta   dsend+1,x  ; Send ONE (5 cyc)
C6AD: 2A       >290           rol              ; Bit 5 to Carry
C6AE: 90 33    >291           bcc   :bit50     ; Handle zero
C6B0: 9D 5B C0 >292           sta   dsend+1,x  ; Send ONE (5 cyc)
C6B3: 2A       >293           rol              ; Bit 4 to Carry
C6B4: 90 38    >294           bcc   :bit40     ; Handle zero
C6B6: 9D 5B C0 >295           sta   dsend+1,x  ; Send ONE (5 cyc)
C6B9: B0 BA    >296           bcs   :sendlo    ; Send low 4 bits.
               >297  
 
                     ===== Page 20 -  October 20, 2004 =====
 
C6BB: 8D 5A C0 >298  :bit70   sta   dsend+0    ; Send ZERO (4 cyc)
C6BE: 2A       >299           rol              ; Bit 6 to Carry
C6BF: 90 11    >300           bcc   :bit60     ; Handle zero
C6C1: 9D 5B C0 >301           sta   dsend+1,x  ; Send ONE (5 cyc)
C6C4: 2A       >302           rol              ; Bit 5 to Carry
C6C5: 90 1C    >303           bcc   :bit50     ; Handle zero
C6C7: 9D 5B C0 >304           sta   dsend+1,x  ; Send ONE (5 cyc)
C6CA: 2A       >305           rol              ; Bit 4 to Carry
C6CB: 90 21    >306           bcc   :bit40     ; Handle zero
C6CD: 9D 5B C0 >307           sta   dsend+1,x  ; Send ONE (5 cyc)
C6D0: B0 A3    >308           bcs   :sendlo    ; Send low 4 bits.
               >309  
C6D2: 8D 5A C0 >310  :bit60   sta   dsend+0    ; Send ZERO (4 cyc)
C6D5: 2A       >311           rol              ; Bit 5 to Carry
C6D6: 90 0B    >312           bcc   :bit50     ; Handle zero
C6D8: 9D 5B C0 >313           sta   dsend+1,x  ; Send ONE (5 cyc)
C6DB: 2A       >314           rol              ; Bit 4 to Carry
C6DC: 90 10    >315           bcc   :bit40     ; Handle zero
C6DE: 9D 5B C0 >316           sta   dsend+1,x  ; Send ONE (5 cyc)
C6E1: B0 92    >317           bcs   :sendlo    ; Send low 4 bits.
               >318  
C6E3: 8D 5A C0 >319  :bit50   sta   dsend+0    ; Send ZERO (4 cyc)
C6E6: 2A       >320           rol              ; Bit 4 to Carry
C6E7: 90 05    >321           bcc   :bit40     ; Handle zero
C6E9: 9D 5B C0 >322           sta   dsend+1,x  ; Send ONE (5 cyc)
C6EC: B0 87    >323           bcs   :sendlo    ; Send low 4 bits.
               >324  
C6EE: 8D 5A C0 >325  :bit40   sta   dsend+0    ; Send ZERO (4 cyc)
C6F1: 90 82    >326           bcc   :sendlo    ; Send low 4 bits.
               >327  
C6F3: 88       >328  :done    dey              ; Prepare to send ckbyte
C6F4: CE 94 02 >329           dec   sendck     ; Ckbyte flag set?
C6F7: F0 A8    >330           beq   :senda     ; -Yes, send ckbyte.
C6F9: 28       >331           plp              ; -No, restore int state
C6FA: 60       >332  :exit    rts              ;   and return with C clear.
 
                     ===== Page 21 -  October 20, 2004 =====
  
               >334  **********************************************************
               >335  *                                                        *
               >336  *                      R C V P K T                       *
               >337  *                                                        *
               >338  *           Michael J. Mahon - April 15, 1996            *
               >339  *                 Revised Oct 13, 2004                   *
               >340  *                                                        *
               >341  *             Copyright (c) 1996, 2003, 2004             *
               >342  *                                                        *
               >343  *  Receives (X) bytes (1..256) starting at (A,Y) from    *
               >344  *  the sending machine.                                  *
               >345  *                                                        *
               >346  *  If no packet is detected within the minimum arb time  *
               >347  *  plus 'tolim'-1 times 2.8ms, it returns with carry set *
               >348  *  and A = 0.                                            *
               >349  *                                                        *
               >350  *  If packet is received, but checksum doesn't compare,  *
               >351  *  it returns with carry set and A <> 0.                 *
               >352  *                                                        *
               >353  *  RCVPKT does the following steps:                      *
               >354  *     1. Detect 'start signal' ONE                       *
               >355  *     2. Put Zip Chip in 'slow mode' for >38,000 cycles  *
               >356  *     3. Sync to middle 6 cycles of data cells           *
               >357  *     3. Receive (X) bytes (at 108 +0/-4 cycles/byte)    *
               >358  *     4. Receive check byte and verify correctness       *
               >359  *                                                        *
               >360  *  RCVCTL performs a RCVPKT to the control packet        *
               >361  *  receive buffer 'rbuf'.                                *
               >362  *                                                        *
               >363  *  RCVPTR performs a RCVPKT to the address in 'ptr' with *
               >364  *  length (X).                                           *
               >365  *                                                        *
               >366  **********************************************************
               >367  *                                                        *
               >368  *                 Implementation Note                    *
               >369  *                                                        *
               >370  *  RCVPKT maintains synchronization with the data stream *
               >371  *  by using a "digital PLL" technique.  The RCVPKT byte  *
               >372  *  loop is 2 cycles longer than the send loop.  When     *
               >373  *  RCVPKT samples the servo transition and finds that it *
               >374  *  has already happened, it subtracts 4 cycles from the  *
               >375  *  loop time, bringing the loop back into optimal sync.  *
               >376  *                                                        *
               >377  *  The effect is to keep the data sampling window on the *
               >378  *  2nd to 7th cycle of 8 stable data cycles, in spite of *
               >379  *  the send loop and receive loop buffers crossing pages *
               >380  *  at different points in a packet and speed variation   *
               >381  *  on the sending or receiving machines of +/- 1% clock  *
               >382  *  frequency relative to each other.                     *
               >383  *                                                        *
               >384  **********************************************************
               >385  
C6FB: A9 89    >386  RCVCTL   lda   #<rbuf     ; Receive control pkt to 'rbuf'
C6FD: A0 02    >387           ldy   #>rbuf     
C6FF: A2 08    >388           ldx   #lenctl    
C701: 85 ED    >389  RCVPKT   sta   ptr        ; A = buf address lo
C703: 84 EE    >390           sty   ptr+1      ; Y = buf address hi
C705: 86 EB    >391  RCVPTR   stx   leng       ; X = length 1..256 (0=>256)
C707: 86 EC    >392           stx   ckbyte     ; Seed 'ckbyte' with length
C709: AC 93 02 >393           ldy   tolim      ; Wait <= (tolim-1) * 2.8ms.
C70C: A2 5C    >394           ldx   #arbx      ;  plus minimum arb time.
C70E: 08       >395           php              ; Save interrupt state
C70F: 78       >396           sei              ;  and disable interrupts.
C710: CD E8 C0 >397           cmp   zipslow    ; Slow any Zip Chip to 1 MHz.
C713: 2C 62 C0 >398  :waitstr bit   drecv      ; Wait for starting ONE.
C716: 30 0C    >399           bmi   :gotit     
C718: CA       >400           dex              ; (inner loop is 11 cycles)
C719: D0 F8    >401           bne   :waitstr   ; Keep waiting...
C71B: 2C 30 C0 >403           bit   spkr       ; "Wait" light on if ROM
C71E: 88       >405           dey              ; (outer loop is 2820 cycles)
 
                     ===== Page 22 -  October 20, 2004 =====
 
C71F: D0 F2    >406           bne   :waitstr   ; Loop for 'timeout' ms.
C721: 98       >407           tya              ; Signal timeout (A = 0)
C722: F0 7B    >408           beq   :err       ;  and return with C set.
               >409  
C724: CD E8 C0 >410  :gotit   cmp   zipslow    ; Slow Zip Chip for packet.
C727: 2C 62 C0 >411  :wait0   bit   drecv      ; Wait for 10-cycle ZERO
C72A: 30 FB    >412           bmi   :wait0     ;  (Coarse sync: d = 7 cyc)
C72C: 2C 62 C0 >413           bit   drecv      ; Read fine sync (d = 4 cyc)
C72F: 30 02    >414           bmi   :late      ; - Late, make up 3 cyc
C731: D5 00    >415           cmp   0,x        ; - Early, delay 6 tot
C733: A2 FF    >416  :late    ldx   #px        ; (Set X to force page crossing)
C735: A0 00    >417           ldy   #0         ; Initialize ptr = 0.
C737: 48       >418           pha              ; Delay 9 cycles
C738: 68       >419           pla              
C739: EA       >420           nop              
               >421  *-------------------------; <-- start of 9-cycle/bit code
C73A: 3E 63 BF >422  :nxbyte  rol   drecv-px,x ; C <-- data (on cycle 5 of 7)
C73D: 2A       >423           rol              ; Shift bit 7 in.
C73E: 3E 63 BF >424           rol   drecv-px,x ; C <-- bit 6
C741: 2A       >425           rol              
C742: 3E 63 BF >426           rol   drecv-px,x ; C <-- bit 5
C745: 2A       >427           rol              
C746: 3E 63 BF >428           rol   drecv-px,x ; C <-- bit 4
C749: 2A       >429           rol              
C74A: C5 00    >430           cmp   0          ; (Bit 4 is stretched 3 cycles)
C74C: 3E 63 BF >431           rol   drecv-px,x ; C <-- bit 3
C74F: 2A       >432           rol              
C750: 3E 63 BF >433           rol   drecv-px,x ; C <-- bit 2
C753: 2A       >434           rol              
C754: 3E 63 BF >435           rol   drecv-px,x ; C <-- bit 1
C757: 2A       >436           rol              
C758: 3E 63 BF >437           rol   drecv-px,x ; C <-- bit 0
C75B: 2A       >438           rol              
               >439  *-------------------------; <-- end of 9-cycle/bit code
C75C: 91 ED    >440           sta   (ptr),y    ; Put byte in buffer (5/6 cyc)
C75E: 4D EC 00 >441           eora  ckbyte     ; Compute checksum (4 cyc)
C761: 2C 62 C0 >442           bit   drecv      ; Sample servo transition.
C764: 10 03    >443           bpl   :late2     ; - Late, delay only 3 cyc.
C766: EA       >444           nop              ; - Early, delay net
C767: 30 00    >445           bmi   :late2     ;    of 7 cyc.
C769: 8D EC 00 >446  :late2   staa  ckbyte     ; Save check byte (4 cyc)
C76C: C8       >447           iny              ;  and advance it.
C76D: CC EB 00 >448           cpya  leng       ; Done yet? (4 cyc)
C770: D0 C8    >449           bne   :nxbyte    ; - no.
C772: 48       >450           pha              ; - yes, delay
C773: 68       >451           pla              ;    9
C774: EA       >452           nop              ;     cycles...
               >453  *-------------------------; Read check byte
C775: 3E 63 BF >454           rol   drecv-px,x ; C <-- data (on cycle 5 of 7)
C778: 2A       >455           rol              ; Shift bit 7 in.
C779: 3E 63 BF >456           rol   drecv-px,x ; C <-- bit 6
C77C: 2A       >457           rol              
C77D: 3E 63 BF >458           rol   drecv-px,x ; C <-- bit 5
C780: 2A       >459           rol              
C781: 3E 63 BF >460           rol   drecv-px,x ; C <-- bit 4
C784: 2A       >461           rol              
C785: C5 00    >462           cmp   0          ; (Bit 4 is stretched 3 cycles)
C787: 3E 63 BF >463           rol   drecv-px,x ; C <-- bit 3
C78A: 2A       >464           rol              
C78B: 3E 63 BF >465           rol   drecv-px,x ; C <-- bit 2
C78E: 2A       >466           rol              
C78F: 3E 63 BF >467           rol   drecv-px,x ; C <-- bit 1
C792: 2A       >468           rol              
C793: 3E 63 BF >469           rol   drecv-px,x ; C <-- bit 0
C796: 2A       >470           rol              
               >471  *-------------------------;
C797: 45 EC    >472           eor   ckbyte     ; Check byte = sum?
C799: D0 04    >473           bne   :err       ; -no, error.
C79B: 28       >474           plp              ; -yes, restore int state
C79C: AA       >475           tax              ;   set Z flag from A
 
                     ===== Page 23 -  October 20, 2004 =====
 
C79D: 18       >476           clc              ;    and return.
C79E: 60       >477           rts              
               >478  
C79F: 28       >479  :err     plp              ; Restore interrupt state,
C7A0: 38       >480           sec              ;  set carry,
C7A1: AA       >481           tax              ;   set Z flag from A,
C7A2: 60       >482           rts              ;    and return...
 
                     ===== Page 24 -  October 20, 2004 =====
  
               >522  **********************************************************
               >523  *                                                        *
               >524  *                     R C V L O N G                      *
               >525  *                                                        *
               >526  *             Michael J. Mahon - May 5, 1996             *
               >527  *                                                        *
               >528  *                   Copyright (c) 1996                   *
               >529  *                                                        *
               >530  *  RCVLONG receives 'length' bytes to 'address' from the *
               >531  *  currently sending machine.                            *
               >532  *                                                        *
               >533  *  It receives a series of packets if 'length' is        *
               >534  *  greater than 256 bytes.                               *
               >535  *                                                        *
               >536  *  RCVLONG detects checksum errors and timeouts, and     *
               >537  *  returns with Carry set and A=0 if timeout, and        *
               >538  *  Carry set and A>0 if a checksum error.  Timeouts in   *
               >539  *  this context are protocol errors.  Both kinds of      *
               >540  *  errors are tallyed in counters.                       *
               >541  *                                                        *
               >542  **********************************************************
               >543  
C7A3: A5 FF    >544  RCVLONG  lda   length+1   ; How many 256-byte pages?
C7A5: F0 11    >545           beq   :short     ; - None, just a short pkt.
C7A7: A2 00    >546  :loop    ldx   #0         ; Set 256 byte packet.
C7A9: A5 FC    >547           lda   address    ;  and point to
C7AB: A4 FD    >548           ldy   address+1  ;   data buffer.
C7AD: 20 01 C7 >549           jsr   RCVPKT     ; Receive 256 bytes.
C7B0: B0 14    >550           bcs   :err       ; Receive error detected.
C7B2: E6 FD    >551           inc   address+1  ; Advance to next page
C7B4: C6 FF    >552           dec   length+1   ;  and decrement page
C7B6: D0 EF    >553           bne   :loop      ;   count until done...
C7B8: A6 FE    >554  :short   ldx   length     ; Remaining data length.
C7BA: F0 09    >555           beq   :done      ; -All done.
C7BC: A5 FC    >556           lda   address    
C7BE: A4 FD    >557           ldy   address+1  
C7C0: 20 01 C7 >558           jsr   RCVPKT     ; Receive final packet.
C7C3: B0 01    >559           bcs   :err       ; Keep track of any errors.
C7C5: 60       >560  :done    rts              
               >561  
C7C6: F0 0A    >562  :err     beq   :timeout   ; Split timeouts and cksum errs
               >563           inc16 ckerr      ; Tally check sum error.
C7C8: EE 9C 02 >563           inc   ckerr      ; Increment 16-bit word.
C7CB: D0 03    >563           bne   *+5        ; - No carry.
C7CD: EE 9D 02 >563           inc   ckerr+1    ; Propagate carry.
               >563           eom              
C7D0: A8       >564           tay              ; Clear Z flag (A <> 0)
C7D1: 60       >565           rts              
               >566  
               >567  :timeout inc16 errprot    ; Tally protocol error.
C7D2: EE 9A 02 >567           inc   errprot    ; Increment 16-bit word.
C7D5: D0 03    >567           bne   *+5        ; - No carry.
C7D7: EE 9B 02 >567           inc   errprot+1  ; Propagate carry.
               >567           eom              
C7DA: A8       >568           tay              ; Set Z flag (A = 0)
C7DB: 60       >569           rts              
 
                     ===== Page 25 -  October 20, 2004 =====
  
                77            align 256        ; Align to page boundary
C7DC: 00 00 00  77            ds    *-1/256*256+256-* 
                77            eom              
                78   endcode  equ   *          
                79   pgmaplo  equ   endcode    ; First message buffer page
                80            err   *-1-entry/$800 ; Can't exceed 8 pages
 
 
--End assembly, 1024 bytes, Errors: 0 

Symbol table - alphabetical order:
   ARBTRATE=$C5AB      BELL    =$FF3A   ?  BOOT    =$C42E      COUT    =$FDED
   HOME    =$FC58      MONITOR =$C55A      PRBL2   =$F94A      PRBYTE  =$FDDA
   PREAD   =$FB1E      PWREDUP =$03F4      RCVCTL  =$C6FB      RCVLONG =$C7A3
   RCVPKT  =$C701      RCVPTR  =$C705      REQUEST =$C4EC      RESET   =$C41C
   ROMboot =$01     ?  ROMcksum=$C400   ?  SENDACK =$C600      SENDCTL =$C611
   SENDPKT =$C617      SENDRSP =$C602      SOFTEV  =$03F2   ?  VBL     =$C019
V  ]cpx    =$0B     V  ]cpy    =$0B04   V  ]cy     =$4FB0   MV ]delay  =$C512
MV ]dly    =$C510   V  ]prod   =$00     V  ]rem    =$03FC   V  ]ym1    =$00
   address =$FC        adr     =$04     MD align   =$8000      an      =$C058
?  an0     =$C058      an1     =$C05A   ?  an2     =$C05C   ?  an3     =$C05E
   arbtime =$01        arbx    =$5C        arbxv   =$0291      arby    =$01
   arbyv   =$0292   ?  bootcnt =$32        bootct  =$FA        bootdly =$03E8
   bootself=$03CC      bootwait=$1388      bufend  =$BF00      bufstrt =$2000
   ckbyte  =$EC        ckerr   =$029C      crate   =$00        cyperms =$03FC
MD delay   =$8000   MD dlyms   =$8000      drecv   =$C062      dsend   =$C05A
   dsk6off =$C0E8      dst     =$02        endcode =$C800      entry   =$C401
   errprot =$029A      frm     =$03        gapwait =$0A        idlen   =$0C
   idletime=$14        idleto  =$08        idmsg   =$C410   MD inc16   =$8000
   keybd   =$C000      len     =$06        lenctl  =$08        leng    =$EB
   length  =$FE     ?  locaddr =$0295      master  =$00        maxgap  =$65
?  maxreq  =$0A     ?  maxreqrt=$03        maxretry=$96        mod     =$01
?  monitor =$C40D      monlen  =$08     MD mov16   =$8000      mserve  =$00
?  nadapage=$03CF      pb      =$C061   ?  pb0     =$C061      pb1     =$C062
?  pb2     =$C063   ?  pgmaplo =$C800      ptr     =$ED        ptrig   =$C070
   px      =$FF        r_BOOT  =$07     ?  r_BPOKE =$08     ?  r_CALL  =$03
   r_GETID =$06     ?  r_GETMSG=$05     ?  r_PEEK  =$01     ?  r_PEKINC=$09
?  r_POKE  =$02     ?  r_PUTMSG=$04        rbuf    =$0289   ?  rcvpkt  =$C407
?  rcvptr  =$C40A      req     =$00     ?  reqctr  =$029E      reqdelay=$11
   reqretry=$0297      reqtime =$0BB8      reqto   =$01        retrycnt=$0299
   retrylim=$0298      rm_ACK  =$02        rm_DACK =$03        rm_NAK  =$04
   rm_REQ  =$01        rqperiod=$14        sbuf    =$0281      self    =$0280
   sendck  =$0294   ?  sendpkt =$C404   ?  servecnt=$029F      setid   =$C4D8
   spkr    =$C030      toflg1  =$DE        toflg2  =$AD        tolim   =$0293
?  warmstrt=$03CD      zipslow =$C0E8   

Symbol table - numerical order:
   master  =$00        crate   =$00        mserve  =$00     V  ]ym1    =$00
V  ]prod   =$00        req     =$00        ROMboot =$01        arbtime =$01
   arby    =$01        reqto   =$01        mod     =$01     ?  r_PEEK  =$01
   rm_REQ  =$01        dst     =$02     ?  r_POKE  =$02        rm_ACK  =$02
?  maxreqrt=$03        frm     =$03     ?  r_CALL  =$03        rm_DACK =$03
   adr     =$04     ?  r_PUTMSG=$04        rm_NAK  =$04     ?  r_GETMSG=$05
   len     =$06        r_GETID =$06        r_BOOT  =$07        idleto  =$08
   lenctl  =$08     ?  r_BPOKE =$08        monlen  =$08     ?  r_PEKINC=$09
   gapwait =$0A     ?  maxreq  =$0A     V  ]cpx    =$0B        idlen   =$0C
   reqdelay=$11        idletime=$14        rqperiod=$14     ?  bootcnt =$32
   arbx    =$5C        maxgap  =$65        maxretry=$96        toflg2  =$AD
   toflg1  =$DE        leng    =$EB        ckbyte  =$EC        ptr     =$ED
   bootct  =$FA        address =$FC        length  =$FE        px      =$FF
   self    =$0280      sbuf    =$0281      rbuf    =$0289      arbxv   =$0291
   arbyv   =$0292      tolim   =$0293      sendck  =$0294   ?  locaddr =$0295
   reqretry=$0297      retrylim=$0298      retrycnt=$0299      errprot =$029A
   ckerr   =$029C   ?  reqctr  =$029E   ?  servecnt=$029F      bootself=$03CC
?  warmstrt=$03CD   ?  nadapage=$03CF      bootdly =$03E8      SOFTEV  =$03F2
   PWREDUP =$03F4      cyperms =$03FC   V  ]rem    =$03FC   V  ]cpy    =$0B04
 
                     ===== Page 26 -  October 20, 2004 =====
 
   reqtime =$0BB8      bootwait=$1388      bufstrt =$2000   V  ]cy     =$4FB0
MD align   =$8000   MD dlyms   =$8000   MD delay   =$8000   MD mov16   =$8000
MD inc16   =$8000      bufend  =$BF00      keybd   =$C000   ?  VBL     =$C019
   spkr    =$C030      an      =$C058   ?  an0     =$C058      an1     =$C05A
   dsend   =$C05A   ?  an2     =$C05C   ?  an3     =$C05E      pb      =$C061
?  pb0     =$C061      pb1     =$C062      drecv   =$C062   ?  pb2     =$C063
   ptrig   =$C070      dsk6off =$C0E8      zipslow =$C0E8   ?  ROMcksum=$C400
   entry   =$C401   ?  sendpkt =$C404   ?  rcvpkt  =$C407   ?  rcvptr  =$C40A
?  monitor =$C40D      idmsg   =$C410      RESET   =$C41C   ?  BOOT    =$C42E
   setid   =$C4D8      REQUEST =$C4EC   MV ]dly    =$C510   MV ]delay  =$C512
   MONITOR =$C55A      ARBTRATE=$C5AB   ?  SENDACK =$C600      SENDRSP =$C602
   SENDCTL =$C611      SENDPKT =$C617      RCVCTL  =$C6FB      RCVPKT  =$C701
   RCVPTR  =$C705      RCVLONG =$C7A3      endcode =$C800   ?  pgmaplo =$C800
   PRBL2   =$F94A      PREAD   =$FB1E      HOME    =$FC58      PRBYTE  =$FDDA
   COUT    =$FDED      BELL    =$FF3A   